<template>
  <div class="virtually">
    <a-table 
      ref="virtuallyTableRef"
      :rowKey="rowKey"
      :columns="columns" 
      :data-source="list" 
      :loading="loading"
      :expandedRowKeys="expandedRowKeys"
      :pagination="pagination" 
      :scroll="scroll"
      @expand="onExpand"
      @change="onChange"
    >
      <template slot-scope="text, record, index" :slot="slot" v-for="slot in Object.keys($scopedSlots).filter(key => key !== 'expandedRowRender') ">
        <slot :name="slot" v-bind="{text, record, index}"></slot>
      </template>
      <template :slot="slot" v-for="slot in Object.keys($slots)">
        <slot :name="slot"></slot>
      </template>
      <template slot-scope="record, index, indent, expanded" :slot="$scopedSlots.expandedRowRender ? 'expandedRowRender' : ''">
        <slot v-bind="{record, index, indent, expanded}" :name="$scopedSlots.expandedRowRender ? 'expandedRowRender' : ''"></slot>
      </template>
    </a-table>
  </div>
</template>

<script>
import { deepCopyArray, deepCopyObject } from '@/utils/util.js' 

export default {
  props: {
    columns: Array,
    dataSource: Array,
    loading: Boolean,
    expandedRowKeys: Array,
    pagination: {
      type: [Object, Boolean],
      default: false
    },
    rowKey: {
      type: [String, Function],
      default: 'key'
    },
    
  },
  data() {
    return {
      scroll:{x:600},
      scrolly: 0,
      viewHeight: 54, // 每行高度
      viewCount: 50, // 每次展示的数量
      list: [], // 展示 dataSource 数据
      el: null,
      totalY: 0,
      scrollTop: 0,
      moveBase: 10, // 迁移基数
      moveCount: 0, // 迁移次数
      timeout: null,
      direction: 'down',
      bodyWrapperEle: null,
      stop: false,
    }
  },
  created() {
    
  },
  mounted() {
    this.addEvent()
    this.init()
  },
  methods: {
    init() { 
      this.list = this.createList()
      this.setHeight()
      this.setList()
    },
    setHeight() { 
      // 设置整个 Table 的高度
      if (this.expandedRowKeys.length > 0) {
        // 当有展开时，计算所有子项的高度
        let y = 0
        this.expandedRowKeys.forEach(id => {
          let data = this.dataSource.find(e => e.id == id)
          if (data.children && data.children.length > 0) {
            y += data.children.length * this.viewHeight + this.dataSource.length * this.viewHeight
          }
        })
        // console.log(y);
        this.totalY = y
        this.createFooterDiv() // 设置占位div
        this.scrolly = 650
      } else {
        this.scrolly = 0
      }
    },
    setList() {
      // 设置展示数据
      console.log(this.expandedRowKeys);
      if (this.expandedRowKeys.length > 0) {
        this.stop = false
        this.bodyWrapperEle = this.$refs.virtuallyTableRef.$el.querySelector(".ant-table-body");
        this.scrollTop = this.bodyWrapperEle.scrollTop; // 滚动的高度
        this.createFooterDivHeight() 

        let data_item = this.dataSource.find(e => e.id == this.expandedRowKeys[0])
        let list_item = this.list.find(e => e.id == this.expandedRowKeys[0])
        for (let idx = 0; idx < this.viewCount; idx++) {
          let item = data_item.children[idx]
          if (item) {
            list_item.children.push(deepCopyObject(item))
          }
        }
      }
    },
    move() {
      let data_item = this.dataSource.find(e => e.id == this.expandedRowKeys[0])
      if (this.expandedRowKeys.length > 0 && data_item.children.length >= this.viewHeight) {
        this.timeout = null
        let scrollTop = this.bodyWrapperEle.scrollTop; // 滚动的高度
        if (scrollTop >= this.scrollTop) {
          this.direction = 'down'
        } else {
          this.direction = 'up'
        }
        this.scrollTop = scrollTop
        this.createFooterDivHeight()
        let list_item = this.list.find(e => e.id == this.expandedRowKeys[0])
        let children = new Array(this.viewCount)
        const h = this.viewCount * this.viewHeight
        const base = Math.floor(this.scrollTop / h) // 移动过了多少个区间
        const index = Math.floor((this.scrollTop - h * base) / this.viewHeight)  //当前scrollTop在该区间的位置
        let arr = this.setInfo(base, index, h, data_item)
        const viewList = this.$refs.virtuallyTableRef.$el.querySelectorAll(".ant-table-row-level-1")
        let idx = 0
        for (let el of viewList) { 
          let item = data_item.children[arr[idx]['idx']]
          if (item) {
            children[idx] = deepCopyObject(item)
            el.style.transform = arr[idx]['translateY']
            el.style.background = '#fff'
          }
          idx++;
        }
        list_item.children = deepCopyArray(children)
      }
    },
    setInfo(base, index, h, data) {
      // 有以下几种情况
      // A、B、index、C、D
      // B、C为可视区域（o1）、B有可能超出A 到 D（o2）、C 有可能超出 D 到 A（o3）
      // console.log(range);
      // base == 0 向下滑 mod1: base, mod2:base, mod3: base + 1, mod4: base + 1, mod5: base
      // base == 0 向上滑 mod1: base, mod2:base, mod3: base + 1, mod4: base, mod5: base
      // base > 0 向下滑 mod1: base, mod2:base, mod3: base + 1, mod4: base + 1, mod5: base
      // base > 0 向上滑 mod1: base, mod2:base - 1, mod3: base+1, mod4: base, mod5: base - 1
      const count = 10 // 前后各10的范围
      const result = new Array(this.viewCount)
      let range = this.getRange(index, count)
      for (let idx = 0; idx < this.viewCount; idx++) { 
        switch (range[idx]) {
          case 'mod2':
          case 'mod5':
            if (base > 0 && this.direction == 'up') {
              let b = base - 1 >= 0 ? base - 1 : 0
              result[idx] = this.setObject(b, idx, h, data)
            } else {
              result[idx] = this.setObject(base, idx, h, data)
            }
            break;
          case 'mod3':
          case 'mod4':
            if (base == 0 || this.direction == 'down') {
              result[idx] = this.setObject(base + 1, idx, h, data)
            } else {
              result[idx] = this.setObject(base + 1, idx, h, data)
            }
            break;
          default:
            result[idx] = this.setObject(base, idx, h, data)
            break;
        }
      }
      return result
    },
    getRange(index, count) {
      // 取范围
      let res = new Array(this.viewCount)
      // let arr1 = [] // 可视区域
      // let arr2 = [] // 上超出区域
      // let arr3 = [] // 下超出区域
      // let arr4 = [] // 上部到可视的区域
      // let arr5 = [] // 下部到可视的区域
      let start = index - count
      let end = index + count
      for (let idx = start; idx <= end; idx++){
        if (idx < 0) {
          res[this.viewCount + idx] = 'mod2'
          // arr2.push(this.viewCount + idx)
        } else if (idx > this.viewCount - 1) {
          res[idx - this.viewCount] = 'mod3'
          // arr3.push(idx - this.viewCount)
        } else {
          res[idx] = 'mod1'
          // arr1.push(idx)
        }
      }
      if (start > 0) {
        for (let idx = 0; idx < start; idx++){
          res[idx] = res[idx] ? res[idx] : 'mod4'
          // arr4.push(idx)
        }
      }
      if (end < this.viewCount - 1) {
        for (let idx = end + 1; idx < this.viewCount; idx++){
          res[idx] = res[idx] ? res[idx] : 'mod5'
          // arr5.push(idx)
        }
      }
      return res
    },
    setObject(base, idx, h, data) {
      const count = data.children.length
      let i = base * this.viewCount + idx
      i = i - Math.floor(i / count) * count
      return {
        translateY: "translateY(" + base * h + "px)",
        idx: i,
      }
    },
    createFooterDiv() {
      if (this.el) {
        this.el.remove();
      }
      this.el = document.createElement('div')
      this.el.className = 'FooterDiv'
      this.el.style.height = (this.scroll - this.viewCount * this.viewHeight) + 'px'
      this.$refs.virtuallyTableRef.$el.querySelector(".ant-table-body").appendChild(this.el);
      this.createFooterDivHeight() 
    },
    createFooterDivHeight() {
      // 设置占位高度
      // console.log(this.totalY, this.viewCount * this.viewHeight, this.scrollTop);
      if (this.totalY > this.viewCount * this.viewHeight) {
        this.el.style.height = (this.totalY - this.viewCount * this.viewHeight - this.scrollTop) + 'px'
      } else {
        this.clearFooterDivHeight()
      }
    },
    clearFooterDivHeight() {
      // 清除占位高度
      this.el.style.height = 0 + 'px'
    },
    addEvent() {
      this.$refs.virtuallyTableRef.$el.querySelector(".ant-table-body").addEventListener('scroll', this.move, { passive: true })
    },
    createList() {
      return deepCopyArray(this.dataSource.map(item => {
        return {...item, children: [] }
      }))
    },
    onExpand(bool, row) {
      if (bool) {
        this.$emit('update:expandedRowKeys', [row.id]) // 每次只能展开一行
      } else {
        this.$emit('update:expandedRowKeys', [])
        this.clearFooterDivHeight()
      }
      // this.$emit('onExpand', bool, row)
      this.$nextTick(() => {
        this.init()
      })
    },
    onChange(pagination, filters, sorter, {currentDataSource}) {
      this.$emit('change', pagination, filters, sorter, {currentDataSource})
    },
  },
  watch: {
    scrolly(val) {
      if (val > 0) {
        this.scroll = { x: 600, y: val }
      } else {
        this.scroll = { x: 600 }
      }
    },
    dataSource() {
      this.list = this.createList()
    }
  }
}
</script>

<style lang="less">
.virtually{
  
}
</style>